﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Controls;
using System.Windows.Forms;
using UrlHistoryLibrary;
using WebAutoUtils;
using WebAutomation;
using mshtml;
using ListView = System.Windows.Forms.ListView;
using RichTextBox = System.Windows.Forms.RichTextBox;

namespace WebAuto
{
    public partial class IERecorder : Form
    {
        public enum ElementIdentifier
        {
            id=0,
            name=1,
            cssClass=2,
            value=3,
            any=4
        }

        public string SavePhysicalFileName, SaveResultsFolder, SaveRepoFolder;

        private Dictionary<string, Dictionary<string, string>> listOfTestLines =new Dictionary<string, Dictionary<string, string>>(); 
        private HTMLDocument doc = null;
        private bool _isOnFocusCalled = false;
        private bool _hasIframe = false;
        private DateTime StartPageLoad = DateTime.Now;
        private DateTime EndPageLoad = DateTime.Now;
        private ArrayList _urlHistory = new ArrayList();
        public IERecorder()
        {
            InitializeComponent();
        }

        private void _addTestHeader()
        {
            rtbTestLines.Text = "";
            rtbTestLines.Text = "Browser?Data|#0,#1,#2,#3,#4,#5,#6,#7,#8,#9,#excel>";


        }

        private void _navigateToUrl(string url)
        {
           
            webBrowser1.Navigate(url);
            _addTestHeader();

        }

        private void btnGo_Click(object sender, EventArgs e)
        {
            StartPageLoad = DateTime.Now;
            EndPageLoad = DateTime.Now;
            _navigateToUrl(txtURL.Text);

        }

       

        private string _getElementAttribute(mshtml.IHTMLEventObj e, string attrName)
        {
            string returnValue = "";
            try
            {
                returnValue = e.srcElement.getAttribute(attrName);

            }
            catch (Exception ex)
            {

            }


            return returnValue;
        }

        private string _getElementIdentifier(mshtml.IHTMLEventObj e, ElementIdentifier elementIdentifier = ElementIdentifier.any)
        {
            string idOrNameOrClass = "";
            try
            {

                switch(elementIdentifier)
                {
                    case ElementIdentifier.id:
                        idOrNameOrClass = e.srcElement.getAttribute("id");
                        break;
                    case ElementIdentifier.name:
                        idOrNameOrClass = e.srcElement.getAttribute("name");
                        break;
                    case ElementIdentifier.cssClass:
                        idOrNameOrClass = e.srcElement.className;
                        break;
                    case ElementIdentifier.value:
                        idOrNameOrClass = e.srcElement.getAttribute("value");
                        break;
                    case ElementIdentifier.any:
                        idOrNameOrClass = e.srcElement.getAttribute("name");

                            if (string.IsNullOrEmpty(idOrNameOrClass))
                            {
                                idOrNameOrClass = e.srcElement.getAttribute("id");
                            }
                            if (string.IsNullOrEmpty(idOrNameOrClass))
                            {
                                idOrNameOrClass = e.srcElement.className;
                            }
                            if (string.IsNullOrEmpty(idOrNameOrClass))
                            {
                                idOrNameOrClass = e.srcElement.getAttribute("value");
                            }
                        break;

                }
                
            }
            catch (Exception ex)
            {

            }



            return idOrNameOrClass;

        }

        private string _getElementType(mshtml.IHTMLEventObj e)
        {
            string returnValue = "";
            try
            {
                returnValue = e.srcElement.getAttribute("type");
                string tag = e.srcElement.tagName.ToLower();
                if (tag=="a")
                {
                    returnValue = "";
                }
                if (string.IsNullOrEmpty(returnValue))
                {
                    //check if link element
                    if (!string.IsNullOrEmpty(e.srcElement.getAttribute("href")))
                    {
                        returnValue = "link";

                    }

                }
            }
            catch (Exception ex)
            {

            }


            return returnValue;
        }


        private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            EndPageLoad = DateTime.Now;
            if (doc == null)
            {
                doc = (mshtml.HTMLDocument)webBrowser1.Document.DomDocument;
               
                //iEvent.onselectionchange +=new HTMLDocumentEvents2_onselectionchangeEventHandler(iEvent_onselectionchange);
               // iEvent.onfocusin +=new HTMLDocumentEvents2_onfocusinEventHandler(iEvent_onfocusin);
            }
            mshtml.HTMLDocumentEvents2_Event iEvent;
            _hasIframe = false;
            if (webBrowser1.Document.Window.Frames.Count > 0)
            {
                try
                {
                    for (int i = 0; i <= webBrowser1.Document.Window.Frames.Count - 1; i++)
                    {

                        var frame = webBrowser1.Document.Window.Frames[i].Document;
                        if (frame.Url.ToString() != "about:blank")
                        {
                            if (!frame.Url.ToString().ToLower().Contains("javascript"))
                            {
                                _hasIframe = true;
                            }
                        }
                    }
                }catch(UnauthorizedAccessException unEx)
                {
                    
                }
            }
            if (_hasIframe)
            {
                doc = (mshtml.HTMLDocument)webBrowser1.Document.Window.Frames[0].Document.DomDocument;
            }
            iEvent = (mshtml.HTMLDocumentEvents2_Event)doc;
            iEvent.onclick += new mshtml.HTMLDocumentEvents2_onclickEventHandler(ClickEventHandler);
            iEvent.onkeyup += new HTMLDocumentEvents2_onkeyupEventHandler(iEvent_onkeyup);
            iEvent.onfocusout += new HTMLDocumentEvents2_onfocusoutEventHandler(iEvent_onfocusout);
            btnClearTest.Enabled = true;
            btnDebugTest.Enabled = true;
            btnSaveTest.Enabled = true;
           // lblSecondsToLoad.Text = Convert.ToDouble((EndPageLoad-StartPageLoad).Seconds).ToString("F")+" sec(s) to load";

        }

        private void iEvent_onfocusout(mshtml.IHTMLEventObj e)
        {
            string txt = _getElementAttribute(e, "value");
            string elementType = _getElementType(e);
            string line = "";
            string idOrNameOrClass = _getElementIdentifier(e);
          
            string replaceValue = "";
            string replaceValue2 = "";
            string replaceValueWith = "";
            if (!string.IsNullOrEmpty(txt) && (elementType == "select-one" || elementType == "select"))
            {
                replaceValue = "Element?SelectValue|" + idOrNameOrClass + ":";
                replaceValueWith = "Element?SelectValue|" + idOrNameOrClass + ":" + txt + ">";

                int i = 0;
                bool hasValue = false;
                foreach (var items in rtbTestLines.Lines)
                {
                    string ln = items;
                    if (ln.Contains(replaceValue))
                    {
                        hasValue = true;

                        rtbTestLines.Select(rtbTestLines.GetFirstCharIndexFromLine(i), items.Length);

                        rtbTestLines.SelectedText = replaceValueWith;
                        break;
                    }
                    i++;
                }

               // Thread.Sleep(3000);
            }
            

        }

        private void iEvent_onkeyup(mshtml.IHTMLEventObj e)
        {
            string txt = _getElementAttribute(e, "value");
            string elementType = _getElementType(e);
            string line = "";
            string idOrNameOrClass = _getElementIdentifier(e);
            if (elementType != "link" && elementType != "")
            {
                if (string.IsNullOrEmpty(idOrNameOrClass))
                {
                    MessageBox.Show(
                        "The element you selected does not have a valid identifier eg ID or name or class.(This web page has been badly coded)");
                    return ;
                }
            }
            string replaceValue = "";
            string replaceValue2 = "";
            string replaceValueWith = "";
            if(e.keyCode==9)
            {
                _onClickOnFocus(e);
            }
            if (!string.IsNullOrEmpty(txt))
            {
                switch (elementType)
                {
                    case "text":
                    case "password":
                        replaceValue = "TextBox?Type|" + idOrNameOrClass + ":";
                        replaceValueWith = "TextBox?Type|" + idOrNameOrClass + ":" + txt + ">";
                        break;
                   

                }

                int i = 0;
                bool hasValue = false;
                foreach(var items in rtbTestLines.Lines)
                {
                    string ln = items;
                    if(ln.Contains(replaceValue))
                    {
                        hasValue = true;
                        
                        rtbTestLines.Select(rtbTestLines.GetFirstCharIndexFromLine(i), items.Length);
                        
                        rtbTestLines.SelectedText = replaceValueWith;
                        break;
                    }
                    i++;
                }
                

            }
            
        }

       

        private bool ClickEventHandler(mshtml.IHTMLEventObj e)
        {


            _onClickOnFocus(e);
            return true;
        }

       

        private void _onClickOnFocus(mshtml.IHTMLEventObj e)
        {
            string elementType = _getElementType(e);
            string idOrNameOrClass = "";
            idOrNameOrClass = _getElementIdentifier(e);
            
            if (elementType != "link" && elementType!="")
            {
                if (string.IsNullOrEmpty(idOrNameOrClass))
                {
                    MessageBox.Show(
                        "The element you selected does not have a valid identifier eg ID or name or class.(This web page has been badly coded)");
                    return ;
                }
            }
            e.srcElement.style.setAttribute("background-color", "yellow");
            string value = "";
            string orginalLines = rtbTestLines.Text;
            string line = "";
            switch (elementType)
            {
                case "text":
                case "password":
                    line = "TextBox?Type|" + idOrNameOrClass + ":";
                    break;
                case "submit":
                    line = "Button?Click|" + idOrNameOrClass + ">";
                    break;
                case "link":
                    value = _getElementAttribute(e, "href");
                    if (value.Contains("javascript"))
                    {
                        idOrNameOrClass = _getElementIdentifier(e, ElementIdentifier.cssClass);
                        if (string.IsNullOrEmpty(idOrNameOrClass))
                        {
                            idOrNameOrClass = _getElementIdentifier(e, ElementIdentifier.any);
                        }
                        line = "Link?Click|" + idOrNameOrClass + ">";
                    }
                    else
                    {
                        if (value.Contains("#"))
                        {
                            line = "Link?Click|" + idOrNameOrClass + ">";
                        }
                        else
                        {
                            line = "Browser?Redirect|" + value + ">";
                        }
                    }
                    break;
                case "select":
                case "select-one":
                    value = _getElementAttribute(e, "value");
                    line = "Element?SelectValue|" + idOrNameOrClass + ":";
                    int lineNo = 0;
                    if (_containsLine(line, ref lineNo))
                    {
                        _removeLine(lineNo);
                        line = "Element?SelectValue|" + idOrNameOrClass + ":" + value;
                    }
                    break;
                case "checkbox":
                    value = _getElementAttribute(e, "value");
                    if (!string.IsNullOrEmpty(value))
                    {
                        line = "Element?CheckBoxValue|" + idOrNameOrClass + ":" + value + ">";
                    }else
                    {
                        value = _getElementAttribute(e, "id");
                        line = "Element?CheckBoxId|" + idOrNameOrClass + ":" + value + ">";    
                    }
                    
                    break;
                case "radio":
                    value = _getElementAttribute(e, "value");
                    line = "Element?RadioValue|" + idOrNameOrClass + ":" + value + ">";

                    break;
            }

            int i = 0;
            bool hasLine = false;
            foreach (var items in rtbTestLines.Lines)
            {
                string ln = items;
                if (ln.Contains(line))
                {
                    hasLine = true;
                    break;
                }
                i++;
            }
            if (rtbTestLines.Lines.Count() <= 1)
            {
                rtbTestLines.Text += Environment.NewLine;
            }
            if (!hasLine)
            {
                rtbTestLines.Text += line + Environment.NewLine;
            }


            //WaitUntil?Time|8000>\r\n
            i = 0;
            List<string> list = new List<string>();
            foreach (var items in rtbTestLines.Lines)
            {
                if(items.ToLower().Contains("browser?redirect"))
                {
                    list.Add(i.ToString());
                }

                i++;
            }
            if(list.Count>0)
            {
                string[] currentLines = rtbTestLines.Lines;
                List<string> listOfLines = new List<string>(currentLines);
                foreach(var item in list)
                {
                    int lineNoToAddBefore = Convert.ToInt32(item);
                    if(lineNoToAddBefore>0)
                    {
                        bool canInsert = false;
                        if (lineNoToAddBefore-1>0)
                        {
                            canInsert = !listOfLines[lineNoToAddBefore - 1].ToLower().Contains("waituntil?time");
                        }
                        if (canInsert)
                        {
                            listOfLines.Insert(lineNoToAddBefore, "WaitUntil?Time|8000>");
                        }
                    }
                }

                currentLines = listOfLines.ToArray();
                rtbTestLines.Lines = currentLines;
            }
        }

        private bool _containsLine(string line,ref int lineNo)
        {
            int i = 0;
            bool hasLine = false;
            foreach (var items in rtbTestLines.Lines)
            {
                string ln = items;
                if (ln.Contains(line))
                {
                    hasLine = true;
                    break;
                }
                i++;
            }
            lineNo = i;
            return hasLine;
        }

        private void _removeLine(int lineNumber)
        {
            rtbTestLines.Lines[lineNumber].Remove(0);
            string[] currentLines = rtbTestLines.Lines;
            List<string> list = new List<string>(currentLines);
            list.RemoveAt(lineNumber);
            currentLines = list.ToArray();
            rtbTestLines.Lines = currentLines;
        }

       private bool _hasTestDataBeenSet()
       {
           bool returnValue = false;
           if (rtbTestLines.Text.Contains("#0")||
               rtbTestLines.Text.Contains("#1")||
               rtbTestLines.Text.Contains("#2")||
               rtbTestLines.Text.Contains("#3")||
               rtbTestLines.Text.Contains("#4")||
               rtbTestLines.Text.Contains("#5")||
               rtbTestLines.Text.Contains("#6")||
               rtbTestLines.Text.Contains("#7")||
               rtbTestLines.Text.Contains("#8")||
               rtbTestLines.Text.Contains("#9")||
               rtbTestLines.Text.Contains("#excel")
               )
           {
               returnValue = false;
           }else
           {
               returnValue = true;
           }

           return returnValue;
       }

        private void btnSaveTest_Click(object sender, EventArgs e)
        {
            try{
                if (!_hasTestDataBeenSet())
                {
                    MessageBox.Show("The test data has not been set.You can set this data by debugging this test first!");
                    return;
                }
                else
                {
                    if (!Directory.Exists(SaveRepoFolder))
                    {
                        MessageBox.Show("The Test repo directory does not exist!");
                        return;
                    }

                    string saveRepoFolder = SaveRepoFolder + "\\Tests";
                    if (!Directory.Exists(saveRepoFolder))
                    {
                        Directory.CreateDirectory(saveRepoFolder);
                        return;
                    }

                    if (!Directory.Exists(SaveResultsFolder))
                    {
                        MessageBox.Show("The Test results directory does not exist!");
                        return;
                    }

                    if (string.IsNullOrEmpty(SavePhysicalFileName))
                    {
                        MessageBox.Show("The Test physical name cannot be empty!");
                        return;
                    }
                    string saveFileName = SavePhysicalFileName;
                    if (!saveFileName.Contains(".txt"))
                    {
                        saveFileName = saveFileName + ".txt";
                    }
                    string saveFileFullName = saveRepoFolder + "\\" + saveFileName;
                    if (File.Exists(saveFileFullName))
                    {
                        MessageBox.Show("The Test file already exists.Trying change the test physical name!");
                        return;
                    }
                    using (StreamWriter sw = File.CreateText(saveFileFullName))
                    {
                        sw.WriteLine(rtbTestLines.Text);
                        sw.Close();
                    }

                    MessageBox.Show("The Test has been saved successfully!");
                    TestDebug testDebugForm = new TestDebug();
                    testDebugForm.PopulateDebugBox(saveFileFullName);
                    testDebugForm.ShowDialog();

                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error saving test!\n"+ex.Message);
            }
        }

        private void IERecorder_Load(object sender, EventArgs e)
        {
            rtbTestLines.Text = "";
            _addTestHeader();
            rtbTestLines.Text += Environment.NewLine;
            _urlHistory = Utils.GetIEURLHistory();
        }

        public RichTextBox GetTestLines()
        {

            return rtbTestLines;
        }

        private void _setTestData(string browser,string displayName,string physicalFileName,string description,string url,string resultsFolder,string repoFolder,string sqlConnection,string failUrl,int iterations,string excelFileLocation)
        {
            if (!_hasTestDataBeenSet())
            {
                rtbTestLines.Text = rtbTestLines.Text.Replace("#0", browser);
                rtbTestLines.Text = rtbTestLines.Text.Replace("#1", displayName);
                rtbTestLines.Text = rtbTestLines.Text.Replace("#2", physicalFileName);
                rtbTestLines.Text = rtbTestLines.Text.Replace("#3", description);
                rtbTestLines.Text = rtbTestLines.Text.Replace("#4", url);
                rtbTestLines.Text = rtbTestLines.Text.Replace("#5", resultsFolder);
                rtbTestLines.Text = rtbTestLines.Text.Replace("#6", repoFolder);
                rtbTestLines.Text = rtbTestLines.Text.Replace("#7", sqlConnection);
                rtbTestLines.Text = rtbTestLines.Text.Replace("#8", failUrl);
                rtbTestLines.Text = rtbTestLines.Text.Replace("#9", iterations.ToString());
                rtbTestLines.Text = rtbTestLines.Text.Replace("#excel", excelFileLocation);
            }else
            {
                rtbTestLines.SelectionStart = 0;
                rtbTestLines.Text = @"Browser?Data|" + browser + "," + displayName + "," + physicalFileName + "," + description + "," + url + "," + resultsFolder + "," + repoFolder + "," + sqlConnection + "," + failUrl + "," + iterations + "," + excelFileLocation + ">" + Environment.NewLine;
                rtbTestLines.SelectionStart = rtbTestLines.Lines.Count()-2;
            }
            int lastLineIndex = rtbTestLines.Lines.Count();
            if (lastLineIndex>0)
            {
                lastLineIndex = lastLineIndex - 1;
            }
            if (rtbTestLines.Lines[lastLineIndex] != "EndTest?End|true")
            {
                rtbTestLines.Text += Environment.NewLine+"EndTest?End|true";
            }
        }

        public string GetURL()
        {

            return txtURL.Text;
        }

        private void btnDebugTest_Click(object sender, EventArgs e)
        {

            IERecorderTestData frm = new IERecorderTestData(this);
            frm.ShowDialog();

        }

        public void DebugTest(string browser, string displayName, string physicalFileName, string description, string url, string resultsFolder, string repoFolder, string sqlConnection, string failUrl, int iterations,string excelLocation)
        {

            _setTestData(browser, displayName, physicalFileName, description, url, resultsFolder, repoFolder, sqlConnection, failUrl, iterations, excelLocation);
            SavePhysicalFileName = physicalFileName;
            SaveResultsFolder = resultsFolder;
            SaveRepoFolder = repoFolder;
            string tmpFileFullName = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".txt";
            using (StreamWriter sw = File.CreateText(tmpFileFullName))
            {
                sw.WriteLine(rtbTestLines.Text);
                sw.Close();
            }


            TestDebug testDebugForm = new TestDebug();
            testDebugForm.PopulateDebugBox(tmpFileFullName);
            testDebugForm.ShowDialog();
        }



        private void btnAvailableCommands_Click(object sender, EventArgs e)
        {
            AvailableCommands frm = new AvailableCommands();
            frm.ShowDialog();
        }

        private void btnClearTest_Click(object sender, EventArgs e)
        {
            rtbTestLines.Text = "";
            _addTestHeader();
        }

        private void webBrowser1_ProgressChanged(object sender, WebBrowserProgressChangedEventArgs e)
        {
            int currentProgress = (int) e.CurrentProgress;
            int maximumProgress = (int)e.MaximumProgress;
            if (currentProgress > 0)
            {
                progressBar1.Maximum = maximumProgress;
                if (currentProgress <= maximumProgress)
                {
                    progressBar1.Value = currentProgress;
                }
            }

        }

        private void IERecorder_Click(object sender, EventArgs e)
        {
            listView1.Items.Clear();
            listView1.Visible = false;
        }

        private void txtURL_KeyUp(object sender, KeyEventArgs e)
        {
            //if (e.KeyCode.ToString().ToLower() == "return")
            //{
            //    listView1.Items.Clear();
            //    listView1.Visible = false;
            //    _navigateToUrl(txtURL.Text);
            //}
            //if (txtURL.Text.Length == 0)
            //{
            //    listView1.Items.Clear();
            //    listView1.Visible = false;

            //}
            //if (txtURL.Text.Length >= 4)
            //{
            //    List<string> listofSimilarURL = new List<string>();
            //    foreach (var item in _urlHistory)
            //    {
            //        var val = (STATURL)item;
            //        if (val.URL.Contains(txtURL.Text))
            //        {
            //            listofSimilarURL.Add(val.URL);
            //        }
            //    }

            //    if (listofSimilarURL.Count > 0)
            //    {
            //        listView1.Items.Clear();
            //        listView1.Visible = true;
            //        foreach (var item in listofSimilarURL.Take(15))
            //        {
            //            listView1.Items.Add(item);
            //        }

            //    }else
            //    {
            //        listView1.Items.Clear();
            //        bool useGoogleSearch = false;
            //        if (useGoogleSearch)
            //        {
            //            try
            //            {
            //                string webpageUrl = "http://www.google.com/search?ie=UTF-8&q=" + txtURL.Text;
            //                string targetDomain = "";
            //                var linkFinder = new LinkFinderClass();
            //                var links =
            //                    linkFinder.FindLinksToDomainOnWebPage(webpageUrl, targetDomain).ToList().Where(
            //                        i => !i.Attributes["href"].ToLower().Contains("google")).Take(15);
            //                foreach (var items in links)
            //                {
            //                    try
            //                    {
            //                        string url = items.Attributes["href"];
            //                        if (url.Contains("search?q="))
            //                        {
            //                            string[] urlArray = url.Split(new string[] {"&amp;"}, StringSplitOptions.None);
            //                            if (urlArray.Length > 0)
            //                            {
            //                                url = urlArray[0].Replace("search?q=", "");
            //                            }
            //                        }
            //                        if (url.Substring(0, 1) == "/")
            //                        {
            //                            url = url.TrimStart('/');
            //                        }

            //                        //search?q=www.bing.co.za&amp;hl=en&amp;sa=X&amp;nfpr=1&amp;spell=
            //                        if (!string.IsNullOrEmpty(url))
            //                        {
            //                            listView1.Items.Add(url);
            //                        }
            //                    }
            //                    catch
            //                    {
            //                    }
            //                }
            //            }
            //            catch
            //            {
            //            }
            //        }

            //    }

            //}
        }

        private int _lastIndex = -1;
        private void listView1_ItemMouseHover(object sender, ListViewItemMouseHoverEventArgs e)
        {
            
            foreach(System.Windows.Forms.ListViewItem item in listView1.Items)
            {
                item.BackColor = Color.White;
                
            }
            e.Item.BackColor = Color.YellowGreen;
            _lastIndex = e.Item.Index;
            txtURL.Text = e.Item.Text;

        }

        private void listView1_MouseClick(object sender, MouseEventArgs e)
        {
            if(_lastIndex>-1)
            {
                string url = listView1.Items[_lastIndex].Text;
                txtURL.Text = url;
                listView1.Items.Clear();
                listView1.Visible = false;
                _navigateToUrl(txtURL.Text);
            }
        }

        private void txtURL_MouseLeave(object sender, EventArgs e)
        {
          
        }

        private void chkEnableScriptErrors_CheckedChanged(object sender, EventArgs e)
        {
            if(chkEnableScriptErrors.Checked)
            {
                this.webBrowser1.ScriptErrorsSuppressed = false;
            }else
            {
                this.webBrowser1.ScriptErrorsSuppressed = true;
            }
        }

       
       
    }
}
